package user;

import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;

import common.MultiBrowserTest;
import common.SpringFactory;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;


import com.fitso.model.bean.User;
import com.fitso.model.service.user.UserService;
import com.thoughtworks.selenium.Selenium;

/**
 * <p>
 * Exercises the login to Fitso.
 * </p>
 * <p>
 * Dependacies:
 * <ul>
 * <li>{@link UserService} for persisting and deleting a test _user from the
 * data store</li>
 * </ul
 * 
 * @author timothystorm
 */
public class Login extends MultiBrowserTest {
	public Login(Selenium selenium) throws Exception {
		super(selenium);
	}

	private UserService _userService;
	private User _user;
	private static final String EMAIL = "firstNameLastName@fitso.com";
	private static final String PASSWORD = "superSecretPassword";
	private static final String FIRST_NAME = "FirstName";
	private static final String LAST_NAME = "LastName";

	@Before
	public void setUp() throws Exception {
		_userService = (UserService) SpringFactory.getBean("UserService");

		_user = new User();
		_user.setEmail(EMAIL);
		_user.setFirstName(FIRST_NAME);
		_user.setLastName(LAST_NAME);
		_user.setPassword(PASSWORD);
		_userService.save(_user);
	}

	@After
	public void tearDown() {
		super.tearDown();
		_userService.delete(_user);
	}

	@Test
	public void test_login() throws Exception {
		_selenium.open("/");
		_selenium.type("email", EMAIL);
		_selenium.type("password", PASSWORD);
		_selenium.click("//input[@value='Sign In']");
		_selenium.waitForPageToLoad("20000");
		assertTrue(_selenium.isTextPresent(FIRST_NAME));
	}

	@Test
	public void test_login_missing_credentials() throws Exception {
		_selenium.open("/");
		_selenium.click("//input[@value='Sign In']");
		_selenium.waitForPageToLoad("20000");
		assertTrue(_selenium.isTextPresent("Email is required"));
		assertTrue(_selenium.isTextPresent("Password is required"));
	}

	@Test
	public void test_login_missing_email() throws Exception {
		_selenium.open("/");
		_selenium.type("password", PASSWORD);
		_selenium.click("//input[@value='Sign In']");
		_selenium.waitForPageToLoad("20000");
		assertTrue(_selenium.isTextPresent("Email is required"));
		assertFalse(_selenium.isTextPresent("Password is required"));
	}

	@Test
	public void test_login_missing_password() throws Exception {
		_selenium.open("/");
		_selenium.type("email", EMAIL);
		_selenium.click("//input[@value='Sign In']");
		_selenium.waitForPageToLoad("20000");
		assertFalse(_selenium.isTextPresent("Email is required"));
		assertTrue(_selenium.isTextPresent("Password is required"));
	}

	@Test
	public void test_login_invalid_email() throws Exception {
		_selenium.open("/");
		_selenium.type("email", "notAn@EmailAddress");
		_selenium.type("password", PASSWORD);
		_selenium.click("//input[@value='Sign In']");
		_selenium.waitForPageToLoad("20000");
		assertTrue(_selenium.isTextPresent("is not a valid email"));
		assertFalse(_selenium.isTextPresent("Password is required"));
	}

	@Test
	public void test_login_incorrect_email() throws Exception {
		_selenium.open("/");
		_selenium.type("email", "timothystorm@google.com");
		_selenium.type("password", PASSWORD);
		_selenium.click("//input[@value='Sign In']");
		_selenium.waitForPageToLoad("20000");
		assertTrue(_selenium.isTextPresent("Email and/or password incorrect"));
		assertFalse(_selenium.isTextPresent("Password is required"));
	}

	@Test
	public void test_login_incorrect_password() throws Exception {
		_selenium.open("/");
		_selenium.type("email", EMAIL);
		_selenium.type("password", "badPassword");
		_selenium.click("//input[@value='Sign In']");
		_selenium.waitForPageToLoad("20000");
		assertTrue(_selenium.isTextPresent("Email and/or password incorrect"));
		assertFalse(_selenium.isTextPresent("Password is required"));
	}

	@Test
	public void test_navigate_to_landing_before_login() throws Exception {
		_selenium.open("/landing");
		assertThat("Fitso - Fitness Specialized", equalTo(_selenium.getTitle()));
	}

	@Test
	public void test_login_logout_invalidated_session() throws Exception {
		// login
		_selenium.open("/");
		_selenium.type("email", EMAIL);
		_selenium.type("password", PASSWORD);
		_selenium.click("//input[@value='Sign In']");
		_selenium.waitForPageToLoad("30000");
		assertTrue(_selenium.isTextPresent(FIRST_NAME));

		// try going back to login and re-logging in without logging out
		_selenium.goBack();
		assertEquals("Fitso - Fitness Specialized", _selenium.getTitle());
		_selenium.type("email", EMAIL);
		_selenium.type("password", PASSWORD);
		_selenium.click("//input[@value='Sign In']");
		_selenium.waitForPageToLoad("30000");
		assertTrue(_selenium.isTextPresent(FIRST_NAME));

		// sign out
		_selenium.click("link=Sign Out");
		_selenium.waitForPageToLoad("30000");
		assertEquals("Should returned to index", "Fitso - Fitness Specialized", _selenium.getTitle());

		// try navigating back to the landing page
		_selenium.open("/landing");
		_selenium.waitForPageToLoad("30000");
		assertEquals("After logging out the _user should be prevented from navigating to the secure landing page",
				"Fitso - Fitness Specialized", _selenium.getTitle());

		// // try back button to the landing page
		// _selenium.goBack();
		// _selenium.waitForPageToLoad("30000");
		// assertEquals("After logging out the _user should be prevented from using the back button to the secure landing page",
		// "Fitso - Fitness Specialized", _selenium.getTitle());

	}
}
